package com.yanghx.springtarnjms.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;

/**
 * @author yangHX
 * createTime  2019/8/8 21:00
 */
@Service
@Slf4j
public class CustomerService {

    @Resource
    private JmsTemplate jmsTemplate;
    @Resource
    private PlatformTransactionManager transactionManager;


    /**
     * 使用JMS监听器监听消息。
     * 如果是从监听器传来的消息。 JmsListener的事务会覆盖整个方法。在方法执行完后再提交事务。
     * 如果直接调用方法传来消息。  事务只在   jmsTemplate.convertAndSend() 这一行代码中有效
     *
     * @param msg msg
     */
    @JmsListener(destination = "custom:msg:new", containerFactory = "msgFactory")
    public void handle(String msg) {
        log.debug("Get JMS message to from cutomer: {}", msg);
        String replay = "Replied - " + msg;
        jmsTemplate.convertAndSend("customer:msg:reply", replay);
        if (msg.contains("error")) {
            simulateError();
        }
    }


    /**
     * 代码形式管理事务。需要在Config类中配置事务管理器
     *
     * @param msg 消息
     */
    @JmsListener(destination = "customer:msg2:new", containerFactory = "msgFactory")
    public void handle2(String msg) {
        log.debug("Get JMS message2 to from customer: {}", msg);
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setTimeout(15);
        TransactionStatus status = transactionManager.getTransaction(def);

        try {
            String replay = "Replay-2 - " + msg;
            jmsTemplate.convertAndSend("customer:msg:reply", replay);

            if (!msg.contains("error")) {
                transactionManager.commit(status);
            } else {
                transactionManager.rollback(status);
            }
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }


    private void simulateError() {
        throw new RuntimeException("some Data error.");
    }
}
